#!/usr/bin/env python3
#coding:utf-8

__author__ = 'xmxoxo<xmxoxo@qq.com>'


# 人脸识别，以图搜索图
# 类似场景： 刷脸验证；刷脸打卡；刷脸支付；

import os
import sys
import time
import requests
import logging
import json
from faces_lib import *
import streamlit as st

# -----------------------------------------

def call_api (url, data, timeout=30):
    ''' 文本转换成向量, 调用URL接口返回数据
    '''
    try:
        #res = requests.post(url, data=data, timeout=timeout)
        res = requests.post(url, json=data, timeout=timeout)
        res.encoding = 'utf-8'
        logging.info('api return bytes:%d' % len(res.text) )
        # print('url return:', res.text)
        res = json.loads(res.text)
        return res
    except Exception as e:
        print(e)
        return {}


def server():

    st.set_page_config(
        page_title="人脸识别搜索",
        page_icon="favicon.png",
        layout="wide",
        menu_items={"About": "关于脸识别搜索系统"},
    )

    # 隐藏右边的菜单以及页脚
    hide_streamlit_style = """
    <style>
    #MainMenu {visibility: hidden;}
    footer {visibility: hidden;}
    </style>
    """
    st.markdown(hide_streamlit_style, unsafe_allow_html=True)


    st.header('人脸识别搜索')
    st.text('功能说明: 人脸识别搜索')
    st.write('---')

    uploaded_file = st.file_uploader("上传图像:", type=['jpg','png','jpeg'])
    if uploaded_file is None:
        st.write('上传后可预览。')
    else:
        begin = time.time()

        col1, col2 = st.columns(2)
        with col1:
            # 显示原图
            st.image(uploaded_file, caption='原图', width=400) #, use_column_width=True

        img_bin = uploaded_file.read()
        # 将图片进行base64编码
        # print('img_bin:', type(img_bin))
        b64 = get_base64_stream(img_bin)

        # 调用接口 查找图片中的人脸
        url = 'http://127.0.0.1:9505/face'
        url = 'http://192.168.15.111:9505/face'
        data = {"image": b64}
        ret = call_api (url, data)

        # 读取返回结果
        faces_b64 = ret.get('faces', [])
        total_faces = len(faces_b64)
        if total_faces==0:
            st.write('未识别到人脸...')
            st.stop()

        # base64转图像
        oimage_b64 = ret.get('oimage', '')
        oimage = base64toarray(oimage_b64)
        with col2:
            st.image(oimage, caption='人脸检测结果', width=400)
        st.write('---')
        st.write('识别到人脸:%d张...'% total_faces)

        # 人脸匹配接口
        url = 'http://127.0.0.1:9505/search'
        url = 'http://192.168.15.111:9505/search'
        data = {"faces": faces_b64}
        ret_search = call_api (url, data)
        total_time = (time.time() - begin) * 1000
        st.write('搜索用时:%.0f毫秒' % (total_time))
        print('ret_search:', ret_search)

        if ret_search.get("msg", '') == 'OK':
            # 直接提取结果
#            ret_imgs_b64 = ret_search.get('results', [])
#            print('ret_imgs_b64:', len(ret_imgs_b64))
#            for ret_img_b64 in ret_imgs_b64:
#                ret_img = base64toarray(ret_img_b64)
#                st.image(ret_img, caption='')

            # 在客户端合成
            match_results = ret_search.get('match_results', [])
            for i, [results, titles] in enumerate(match_results):
                faces_n = base64toarray(faces_b64[i])
                ret_img = show_result(faces_n, results, titles, showimg=0)
                st.image(ret_img, caption='')
        else:
            st.write('没有匹配到结果!')

def cmd_cli():
    print('正在启动交互命令行...')
    dats, vsearch, persons, model, detector, predictor = model_init()

    while 1:
        pic = input('请输入待识别图像文件路径:[Q退出]:').strip()
        if not pic: continue
        if pic in ['q', 'Q', 'quit', 'Quit'] : break

        if not os.path.exists(pic):
            continue
        print('待搜索图片:%s' % pic)

        begin = time.time()
        # 查找图片中的人脸
        faces, oimage = face_detector(pic, detector, predictor, showwin=0, saveface=0)
        print('已识别人脸数量: %d ...'% len(faces))

        if len(faces)==0:
            print('没有识别到人脸...')
            continue

        # 计算待搜索图片的向量
        print('正在生成向量...')
        sample = load_images(faces)
        query = get_model_scores(model, sample)

        # 搜索向量，注意可能是多个结果
        D, I = vsearch.search(query, top=5)
        total_time = (time.time() - begin) * 1000
        print('搜索用时:%.0f毫秒' % (total_time))

        # print(D, I)
        pics = D.shape[0]

        for n in range(pics):
            print('-'*40)
            rets = zip(I[n],D[n])
            results, titles = [], []
            for i, d in rets:
                #print('d,i:', d,i)
                pid = i
                #pid, pname = dats[i]
                pname = dats[i]
                # 查找人名
                name = persons[i] #find_person(persons, pid)
                #name = find_person(persons, pid)
                # 显示图片
                # cv2.imshow("source face", faces[n])

                picname = './output0/%s/%s' % (name, pname)
                results.append(picname)
                title_text = '相似度:%.2f, 姓名：%s, PID:%s, 图像名:%s' % (d, name, pid, picname)
                print(title_text)

                title = '%s(%.2f)'% (name, d)
                titles.append(title)

            # 显示合成的结果图
            show_result(faces[n], results, titles)

            cv2.waitKey(0)
            cv2.destroyAllWindows()

if __name__ == '__main__':
    pass
    # cmd_cli()
    server()



